package algorithms;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Arrays;
import java.util.List;

import dataStructure.DicHashTreeNode;
import dataStructure.HashTreeNode;
import dataStructure.INode;
import dataStructure.ItemSet;

public class Dic extends Algo {

	DicHashTreeNode root;
	int M = 10000;

	public Dic(String pathFormat, int startIndex, int endIndex) {
		super(pathFormat, startIndex, endIndex);
		root = new DicHashTreeNode(0, 0);
	}

	public Dic(String pathFormat, int startIndex, int endIndex, int _M) {
		super(pathFormat, startIndex, endIndex);
		root = new DicHashTreeNode(0, 0);
		M = _M;
	}

	@Override
	public INode findFrequentItemSet(double support, int minimumK, int maxK) {

		BufferedReader br;
		String line;
		String[] tmpBasket;
		root.depth = 0;
		root.set = null;
		int k = 1;
		long basketIndex = 0;
		DicHashTreeNode singletone;
		boolean foundSomething;

		// First Iteration - we just collect and count the singletons
		iterNum = 1;
		for (int i = fileStartIndex; i <= fileEndIndex; i++) {
			try {
				br = new BufferedReader(new FileReader(String.format(
						filePathFormat, i)));
				while ((line = br.readLine()) != null) {
					if (line.startsWith("#") || line.equals(""))
						// Ignore comments
						continue;
					line = line.toLowerCase();
					tmpBasket = line.split(",");
					// Update counters
					numOfItems += tmpBasket.length;
					numOfBaskets++;
					basketIndex++;

					for (String word : tmpBasket) {
						if (root.childrens.containsKey(word)) {
							root.childrens.get(word).set.counter++;
						} else {
							// We consider all singletons as if they were
							// discovered at
							// the beginning of the algo
							singletone = new DicHashTreeNode(1, 0);
							singletone.set = new ItemSet();
							singletone.set.addItem(word);
							singletone.set.counter = 1;
							singletone.parent = root;
							singletone.keyAtPArent = word;
							root.put(word, singletone);
						}
					}
				}
				br.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// Prune not frequent singletons:
		if (!root.pruneChildrens((int) (support * numOfBaskets)))
			return root;

		// Discover all level 2 candidates
		if (!root.discoverChildrens((int)(support*numOfBaskets),basketIndex))
			return root;

		k = 2;
		
		// All other iterations:
		while (true) {
			foundSomething = false;
			iterNum++;
			for (int i = fileStartIndex; i <= fileEndIndex; i++) {
				try {
					br = new BufferedReader(new FileReader(String.format(
							filePathFormat, i)));
					while ((line = br.readLine()) != null) {
						if (line.startsWith("#") || line.equals(""))
							// Ignore comments
							continue;
						basketIndex++;
						line = line.toLowerCase();
						tmpBasket = line.split(",");

						handleBasket(tmpBasket, k, root, basketIndex,
								(int) (support * numOfBaskets));
						if (basketIndex % M == 0) {
							k++;
							root.pruneAtDepth((int) (support * numOfBaskets),
									numOfBaskets, k, basketIndex);
							if (root.discoverTillDepth(
									(int) (support * numOfBaskets),
									numOfBaskets, k, basketIndex))
								foundSomething = true;
						}
					}
					br.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			System.gc();
			// Sanity checks
			if (!foundSomething)
				break;
			if (basketIndex > maxK * numOfBaskets)
				break;
		}

		return root;
	}

	protected void handleBasket(String[] tmpBasket, int k,
			DicHashTreeNode root, long basketIndex, int absSupport) {
		Arrays.sort(tmpBasket);
		List<List<String>> subsets = Common.getAllSubsets(tmpBasket, k);
		String word;

		if (subsets == null)
			return;
		DicHashTreeNode traverser;
		for (List<String> list : subsets) {
			traverser = root;
			if (traverser.childrens == null)
				continue;
			// Assert(k==list.size())
			for (int i = 0; i < k; i++) {
				word = list.get(i);
				if (traverser.childrens.containsKey(word)) {
					traverser = traverser.childrens.get(word);
					traverser.encounterNode(basketIndex, numOfBaskets,
							absSupport);
				} else {
					break;
				}
			}
		}
	}
}
